home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’92 / FinderMenu ƒ / FinderMenu INIT ƒ / Utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-18  |  14.2 KB  |  736 lines  |  [TEXT/KAHL]

  1. /*
  2.  * (C) 1992 SixxHeads Software
  3.  * All Rights Reserved
  4.  *
  5.  * This stuff is collected from all over
  6.  * the known universe.  If you wrote something
  7.  * and put the source in the public domain, it's
  8.  * probably here.
  9.  * 
  10.  * <Revision History>
  11.  *        04/28/92  smz  Created.
  12.  *        05/16/92  smz  added GetFileModDate()
  13.  */
  14.  
  15. #include "Utils.h"
  16. #include <varargs.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <Finder.h>
  20. #include <GestaltEqu.h>
  21. #include <Traps.h>
  22.  
  23. /* Globally global globals
  24.  */
  25.  
  26. char CrsrCouple : 0x8cf;
  27. char CrsrNew : 0x8ce;
  28. Point MTemp : 0x828;
  29. Point RawMouse : 0x82c;
  30. Point Mouse : 0x830;
  31.  
  32. /*
  33.  * Local Globals
  34.  */
  35. #define MAXPORTSTACK    8
  36.  
  37. GrafPtr portStack[MAXPORTSTACK];
  38. short curPortSP;
  39.  
  40. Boolean IsFinderRunning()
  41. {
  42.     return pstrequal(CurApName, FinderName);
  43. }
  44.  
  45. Boolean HaveGestalt()
  46. {
  47.     return NGetTrapAddress(_GestaltDispatch, OSTrap) != NGetTrapAddress(_Unimplemented, OSTrap);
  48. }
  49.  
  50. Boolean System7Running()
  51. {
  52.     long response;
  53.     if (HaveGestalt())
  54.         if (Gestalt(gestaltSystemVersion, &response) == noErr)
  55.             return response >= 0x0700;
  56.     return false;
  57. }
  58.  
  59. /***********************************************************************************************/
  60.  
  61. Boolean pstrequal(reg unsigned char *p1, reg unsigned char *p2)
  62. {
  63.     reg short len = *p1++;
  64.     
  65.     if (len != *p2++)
  66.         return false;
  67.     
  68.     while (len--)
  69.         if (*p1++ != *p2++)
  70.             return false;
  71.     
  72.     return true;
  73. }
  74.  
  75. Handle MoveToSystemHeap(Handle hRes)
  76. {
  77. #if __option(a4_globals)
  78.     reg long saveZone = *(long*) TheZone;
  79. #endif
  80.     reg Handle hNew;
  81.     reg short size;
  82.     
  83.     size = GetHandleSize(hRes);
  84.     
  85. #if __option(a4_globals)
  86.     *(long *) TheZone = *(long *) SysZone;
  87. #endif
  88.     
  89.     hNew = NewHandle(size);
  90.     
  91. #if __option(a4_globals)
  92.     *(long *) TheZone = saveZone;
  93. #endif
  94.     
  95.     if (hNew == nil) {
  96. #ifdef DEBUG
  97.         DebugStr("\pCouldn't make handle in system heap!");
  98. #endif
  99.         return nil;
  100.     }
  101.     
  102.     BlockMove(*hRes, *hNew, size);
  103.     
  104.     ReleaseResource(hRes);
  105.     
  106.     return hNew;
  107. }
  108.  
  109. Handle CopyToSystemHeap(Handle hMem)
  110. {
  111.     reg Handle hNew;
  112.     reg short size;
  113.     
  114.     size = GetHandleSize(hMem);
  115.     
  116.     hNew = NewHandleSys(size);
  117.  
  118.     if (hNew == nil) {
  119. #ifdef DEBUG
  120.         DebugStr("\pCouldn't make handle in system heap!");
  121. #endif
  122.         return nil;
  123.     }
  124.     
  125.     BlockMove(*hMem, *hNew, size);
  126.     
  127.     return hNew;
  128. }
  129.  
  130. #if 0
  131. void dprintf(const char* format, ...)
  132. {
  133.     va_list args;
  134.     static char str[256];
  135.     int count;
  136.     
  137.     va_start(args, format);
  138.     count = vsprintf(str, format, args);
  139.     va_end(args);
  140.     DebugStr(c2pstr(str));
  141. }
  142.  
  143. void nprintf(const char* format, ...)
  144. {
  145.     va_list args;
  146.     char str[256];
  147.     char buff[256];
  148.     int count;
  149.     Boolean savePatchesInstalled = thePatchesInstalled;
  150.     
  151.     va_start(args, format);
  152.     count = vsprintf(str, format, args);
  153.     va_end(args);
  154.     
  155.     sprintf(buff, "%s: %s", thePatchName, str);
  156.     ParamText(c2pstr(buff), nil, nil, nil);
  157.     Alert(cFinderAlert, nil);
  158.     
  159.     thePatchesInstalled = savePatchesInstalled;
  160. }
  161. #endif
  162.  
  163. //////////////////////////////////////////////////////////////////
  164.  
  165. typedef char smallIconBits[32];
  166. typedef smallIconBits **hdlsmalliconbits;
  167.  
  168. static char unknownBits[] = {
  169.     0x00, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x18, 0x60, 0x18, 
  170.     0x60, 0x18, 0x60, 0x00, 0x60, 0x00, 0xC0, 0x00, 0xC0, 
  171.     0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00,
  172.     0x00, 0x03, 0x00, 0x03, 0x00
  173. };
  174.  
  175. void PlotSicn(Handle hSicn, short ix, Point loc)
  176. {
  177.     Rect dstRect;
  178.     BitMap sicnBits;
  179.     GrafPtr curPort;
  180.     reg hdlsmalliconbits hbits = (hdlsmalliconbits) hSicn;
  181.     short ctSicns = 0;
  182.  
  183.     if (hSicn) {
  184.         ctSicns = GetHandleSize(hSicn) / sizeof(smallIconBits);
  185.         HLock(hSicn);
  186.     }
  187.     
  188.     if (ix < ctSicns && hSicn)
  189.         sicnBits.baseAddr = (Ptr) &(*hbits)[ix];
  190.     else
  191.         sicnBits.baseAddr = unknownBits;
  192.  
  193.     sicnBits.rowBytes = 2;
  194.     sicnBits.bounds.top = sicnBits.bounds.left = 0;
  195.     sicnBits.bounds.bottom = sicnBits.bounds.right = 16;
  196.  
  197.     dstRect = sicnBits.bounds;
  198.     OffsetRect(&dstRect, loc.h, loc.v - 12);
  199.  
  200.     GetPort(&curPort);
  201.     
  202.     CopyBits(&sicnBits, &curPort->portBits, &sicnBits.bounds, &dstRect, srcOr, nil);
  203.  
  204.     if (hSicn)
  205.         HUnlock(hSicn);
  206. }
  207.  
  208. void PushPort(GrafPtr pPort)
  209. {
  210.     GetPort(&portStack[curPortSP++]);
  211. #ifdef DEBUG
  212.     if (curPortSP >= MAXPORTSTACK)
  213.         DebugStr("\ptoo many pushports!");
  214. #endif
  215.     SetPort(pPort);
  216. }
  217.  
  218. void PopPort()
  219. {
  220. #ifdef DEBUG
  221.     if (curPortSP <= 0) {
  222.         DebugStr("\ptoo many popports!");
  223.         return;
  224.     }
  225. #endif
  226.     
  227.     SetPort(&portStack[--curPortSP]);
  228. }
  229.  
  230. //////////////////////////////////////////////////////////////////
  231.  
  232. Boolean IsTargetRunning(long code, ProcessSerialNumber *r)
  233. {
  234.     OSErr result;
  235.     ProcessSerialNumber p;
  236.     ProcessInfoRec info;
  237.     FSSpec procSPec;
  238.     Str255 procName;
  239.     
  240.     if (*(char *) 0x910 == -1)
  241.         return false;
  242.         
  243.     p.highLongOfPSN = 0;
  244.     p.lowLongOfPSN = kNoProcess;
  245.  
  246.     while (GetNextProcess(&p) == noErr) {
  247.         info.processInfoLength = sizeof(ProcessInfoRec);
  248.         info.processName = (void*) &procName;
  249.         info.processAppSpec = &procSPec;
  250.         result = GetProcessInformation(&p, &info);
  251.         if (result != noErr)
  252.             return false;
  253.         if (info.processSignature == code) {
  254.             if (r)
  255.                 *r = p;
  256.             return true;    /* frontier is running! */
  257.         }
  258.     }
  259.     return false;
  260. }
  261.  
  262. void BringAppToFront(reg ProcessSerialNumber *p)
  263. {
  264.     ProcessSerialNumber save;
  265.     GetFrontProcess(&save);
  266.     SetFrontProcess(p);
  267.     *p = save;
  268. }
  269.  
  270. //////////////////////////////////////////////////////////////////
  271.  
  272. void copystring (Str255 source, Str255 dest)
  273. {
  274.     /*
  275.     create a copy of source in dest.  copy the length byte and
  276.     all the characters in the source string.
  277.  
  278.     assume the strings are pascal strings, with the length byte in
  279.     the first character of the string.
  280.     */
  281.  
  282.     reg short i, len;
  283.     
  284.     len = (short) source [0];
  285.     
  286.     for (i = 0; i <= len; i++) 
  287.         dest [i] = source [i];
  288. } /*copystring*/
  289.  
  290. void cstring2pstring(unsigned char *cSource, Str255 dest)
  291. {
  292.     reg short len = strlen((char *) cSource);
  293.     reg char *pDest = (char *) &dest[1];
  294.     dest[0] = len;
  295.     while (len--)
  296.         *pDest++ = *cSource++;
  297. }
  298.  
  299. Boolean pushstring(Str255 bssource, Str255 bsdest)
  300. {
  301.     reg short lensource = bssource [0];
  302.     reg short lendest = bsdest [0];
  303.     reg char *psource, *pdest;
  304.     
  305.     if ((lensource + lendest) > 255)
  306.         return (false);
  307.         
  308.     pdest = (char *) bsdest + (char) lendest + 1;
  309.     
  310.     psource = (char *) bssource + 1;
  311.     
  312.     bsdest [0] += (char) lensource;
  313.     
  314.     while (lensource--) *pdest++ = *psource++;
  315.     
  316.     return (true);
  317. } /*pushstring*/
  318.     
  319.     
  320. Boolean pushlong(long num, Str255 bsdest)
  321. {
  322.     Str255 bsint;
  323.     
  324.     NumToString (num, bsint);
  325.     
  326.     return (pushstring (bsint, bsdest));
  327. } /*pushlong*/
  328.  
  329. void pushchar(char c, Str255 s)
  330. {
  331.     s[++*s] = c;
  332. }
  333.  
  334. short String2Short(Str255 s)
  335. {
  336.     long tmp;
  337.     StringToNum(s, &tmp);
  338.     return (short) tmp;
  339. }
  340.  
  341. Boolean String2Boolean(Str255 tmp)
  342. {
  343.     if (EqualString(tmp, "\p1", false, false))
  344.         return true;
  345.     if (EqualString(tmp, "\ptrue", false, false))
  346.         return true;
  347.     return false;
  348. }
  349.  
  350. Boolean stringtotext(Str255 s, Handle *htext)
  351. {
  352.     reg long len;
  353.     reg Handle h;
  354.     
  355.     len = s [0];
  356.     
  357.     h = NewHandle (len);
  358.     
  359.     if (h == nil)
  360.         return (false);
  361.         
  362.     BlockMove (&s [1], *h, len);
  363.     
  364.     *htext = h;
  365.     
  366.     return (true);
  367. } /*stringtotext*/
  368.     
  369.     
  370. Boolean texttostring(Handle htext, Str255 s)
  371. {
  372.     long len;
  373.     
  374.     len = GetHandleSize (htext);
  375.     
  376.     if (len > 255)
  377.         len = 255;
  378.         
  379.     BlockMove (*htext, &s [1], len);
  380.     
  381.     s [0] = (char) len;
  382.     
  383.     return (true);
  384. } /*texttostring*/
  385.  
  386.  
  387. Handle GetFullPath(short vRefNum, unsigned long parentID, Str255 baseName)
  388. {
  389.     CInfoPBRec    block;
  390.     Str255        directoryName;
  391.     OSErr        err;
  392.     Handle        hFileName;
  393.  
  394. #if __option(a4_globals)
  395.     hFileName = NewHandleSys(0);
  396. #else
  397.     hFileName = NewHandle(0);
  398. #endif
  399.     if (hFileName == nil)
  400.         return nil;
  401.     
  402.     if (parentID != 1) {    // not a disk
  403.         *directoryName = 0;
  404.     
  405.         block.dirInfo.ioNamePtr = (void *) directoryName;
  406.         block.dirInfo.ioDrParID = parentID;
  407.     
  408.         do {
  409.             block.dirInfo.ioVRefNum = vRefNum;
  410.             block.dirInfo.ioFDirIndex = -1;
  411.             block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
  412.     
  413.             err = PBGetCatInfo(&block,false);
  414.             if (err != noErr)
  415.                 goto errorExit;
  416.  
  417.             pushchar(':', directoryName);
  418.             Munger(hFileName, 0, nil, 0, &directoryName[1], *directoryName);
  419.         } while (block.dirInfo.ioDrDirID != fsRtDirID);
  420.     }
  421.  
  422.     if (PtrAndHand(&baseName[1], hFileName, *baseName) != noErr)
  423.         goto errorExit;
  424.  
  425.     if (parentID == 1) { // it's a disk, add a ":"
  426.         if (PtrAndHand(":", hFileName, 1) != noErr)
  427.             goto errorExit;
  428.     }
  429.     
  430.     return hFileName;
  431.     
  432. errorExit:
  433.         DisposeHandle(hFileName);
  434.         return nil;
  435. }
  436.  
  437. static Boolean LookForDuplicates(Handle **hFileList, short ctEntries, Handle hNewName)
  438. {
  439.     reg short i;
  440.     reg short nameLen = GetHandleSize(hNewName);
  441.     reg Handle *pFileList = *hFileList;
  442.  
  443.     if (nameLen <= 0)
  444.         return true;    /* skip blank ones */
  445.  
  446.     for (i = 0;  i < ctEntries;  i++) {
  447.         reg Handle hMem = *pFileList++;
  448.  
  449.         if (hMem == nil) {
  450. #ifdef DEBUG
  451.             DebugStr("\pbad handle in lookforduplicates!");
  452. #endif
  453.             return true;
  454.         }
  455.  
  456.         if (GetHandleSize(hMem) != nameLen)
  457.             continue;
  458.         
  459.         if (! memcmp(*hMem, *hNewName, nameLen))
  460.             return true;
  461.     }
  462.     return false;
  463. }
  464.  
  465. void PushFullPath(CInfoPBPtr info, Handle **hFileList)
  466. {
  467.     if (hFileList) {
  468.         reg short ct = GetHandleSize(hFileList) >> 2;
  469.         Handle newName;
  470.  
  471.         newName = GetFullPath(info->hFileInfo.ioVRefNum, info->dirInfo.ioDrParID, info->hFileInfo.ioNamePtr);
  472.  
  473.         if (newName == nil)
  474.             return;
  475.  
  476.         if (ct > 0 && LookForDuplicates(hFileList, ct, newName)) {
  477.             DisposeHandle(newName);
  478.             return;
  479.         }
  480.  
  481.         Munger(hFileList, 0, nil, 0, &newName, sizeof(Handle));
  482.     }
  483. }
  484.  
  485. /*
  486.  * if the string fits inside the given number of pixels, fine -- do nothing
  487.  * and return.
  488.  * 
  489.  * if not, return a string that does fit, with ellipses representing the 
  490.  * deleted characters.  ellipses are generated by pressing option-semicolon.
  491. */
  492. void ellipsize(Str255 s, short width)
  493. {    
  494.     reg char len;
  495.     reg short newwidth;
  496.     
  497.     if ((newwidth = StringWidth (s)) <= width) /*nothing to do, the string fits*/
  498.         return;
  499.     
  500.     len = s [0]; /* current length in characters*/
  501.     
  502.     width -= CharWidth ('…'); /* subtract width of ellipses*/
  503.         
  504.     do { /*until it fits (or we run out of characters)*/
  505.     
  506.         newwidth -= CharWidth (s [len]);
  507.         
  508.         --len;
  509.     } while ((newwidth > width) && (len != 0));
  510.     
  511.     ++len; /*make room for the ellipses*/
  512.     
  513.     s [len] = '…'; 
  514.     
  515.     s [0] = (char) len;
  516. } /*ellipsize*/
  517.  
  518.  
  519. /*
  520.  * draw the string in the current font, size and style, centered inside
  521.  * the indicated rectangle.
  522.  */
  523. void centerstring(Rect r, Str255 s)
  524. {    
  525.     reg short rh = r.bottom - r.top;
  526.     reg short rw = r.right - r.left;
  527.     reg short h, v;
  528.     FontInfo fi;
  529.  
  530.     GetFontInfo(&fi);
  531.     ellipsize(s, rw); /*make sure it fits inside the rectangle, width-wise*/
  532.     h = r.left + ((rw - StringWidth (s)) / 2);
  533.     v = r.top + ((rh - (fi.ascent + fi.descent)) / 2) + fi.ascent;
  534.     MoveTo(h, v);
  535.     ClipRect(&r);
  536.     DrawString(s);
  537. } /*centerstring*/
  538.  
  539.  
  540. void setfontsizestyle (short fontnum, short fontsize, short fontstyle)
  541. {
  542.     TextFont (fontnum);
  543.     TextSize (fontsize);
  544.     TextFace (fontstyle);
  545. } /*setfontsizestyle*/
  546.     
  547.  
  548. OSType GetProcessCreator(void)
  549. {
  550. #if __option(a4_globals)
  551.     return 'ƒMNU';
  552. #else
  553.     /*
  554.     get the 4-character creator identifier for the application we're running 
  555.     inside of.
  556.     */
  557.     
  558.     ProcessSerialNumber psn;
  559.     ProcessInfoRec info;
  560.     
  561.     if (*(char *) 0x910 == -1)
  562.         return 'XxXX';
  563.  
  564.     GetCurrentProcess(&psn);
  565.     info.processInfoLength = (long) sizeof(info);
  566.     info.processName = nil;
  567.     info.processAppSpec = nil;
  568.     GetProcessInformation(&psn, &info);
  569.     return (info.processSignature);
  570. #endif
  571. } /*GetProcessCreator*/
  572.  
  573. OSType GetFrontProcessCreator()
  574. {
  575.     /*
  576.     get the 4-character creator identifier for the application we're running 
  577.     inside of.
  578.     */
  579.     
  580.     ProcessSerialNumber psn;
  581.     ProcessInfoRec info;
  582.  
  583.     if (*(char *) 0x910 == -1)
  584.         return 'INIT';
  585.  
  586.     GetFrontProcess(&psn);
  587.     info.processInfoLength = (long) sizeof(info);
  588.     info.processName = nil;
  589.     info.processAppSpec = nil;
  590.     GetProcessInformation(&psn, &info);
  591.     return (info.processSignature);
  592. }
  593.  
  594. //////////////////////////////////////////////////////////////////
  595.  
  596. Boolean NewFileRecord(Str255 s, long creator, long type, FileRecord* info)
  597. {
  598.     info->itsDirKnown = false;
  599.     info->itsVRefNum = -1;
  600.     info->itsDirID = -1;
  601.     info->itsRefNum = -1;
  602.     info->itsCreator = creator;
  603.     info->itsType = type;
  604.     info->itsOpen = false;
  605.     copystring(s, info->itsName);
  606.     return true;
  607. }
  608.  
  609. static Boolean CheckPrefsDir(FileRecord *info)
  610. {
  611.     if (info->itsDirKnown == false) {
  612.         if (FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &info->itsVRefNum, &info->itsDirID) == noErr)
  613.             info->itsDirKnown = true;
  614.     }
  615.     return info->itsDirKnown;
  616. }
  617.  
  618. Boolean OpenPrefsFile(FileRecord *info)
  619. {
  620.     if (! CheckPrefsDir(info)) {
  621. #ifdef DEBUG
  622.         DebugStr("\pcan't find prefs folder!");
  623. #endif
  624.         return false;
  625.     }
  626.     info->itsRefNum = HOpenResFile(info->itsVRefNum, info->itsDirID, info->itsName, fsRdWrPerm);
  627.     if (info->itsRefNum == -1)
  628.         return false;
  629.     info->itsOpen = true;
  630.     info->itsModDate = GetFileModDate(info);
  631.     return true;
  632. }
  633.  
  634. Boolean ClosePrefsFile(FileRecord* info)
  635. {
  636.     if (info->itsOpen) {
  637.         CloseResFile(info->itsRefNum);
  638.         info->itsOpen = false;
  639.         return true;
  640.     }
  641.     return false;
  642. }
  643.  
  644. OSErr CreatePrefsFile(FileRecord* info)
  645. {
  646.     OSErr err;
  647.     
  648.     if (info->itsOpen)
  649.         ClosePrefsFile(info);
  650.     if (! CheckPrefsDir(info)) {
  651. #ifdef DEBUG
  652.         DebugStr("\pcan't find prefs folder");
  653. #endif
  654.         return false;
  655.     }
  656.     err = Create(info->itsName, info->itsVRefNum, info->itsCreator, info->itsType);
  657.     if (err == noErr)
  658.         info->itsModDate = GetFileModDate(info);
  659.     return err;
  660. }
  661.  
  662. unsigned long GetFileModDate(FileRecord* info)
  663. {
  664.     HFileInfo fileInfo;
  665.     short ctItems;
  666.     
  667.     fileInfo.ioCompletion = nil;
  668.     fileInfo.ioNamePtr = (void*) &info->itsName;
  669.     fileInfo.ioVRefNum = info->itsVRefNum;
  670.     fileInfo.ioFDirIndex = 0;
  671.     fileInfo.ioDirID = info->itsDirID;
  672.     
  673.     if (PBGetCatInfo(&fileInfo, false) != noErr)
  674.         return 0;    /* error */
  675.  
  676.     return fileInfo.ioFlMdDat;
  677. }
  678.  
  679. Boolean PrefsFileChanged(FileRecord* info)
  680. {
  681.     return info->itsModDate != GetFileModDate(info);
  682. }
  683.  
  684. //////////////////////////////////////////////////////////////////
  685.  
  686. MenuHandle FindInstalledMenu(short menuID, short *leftEdge)
  687. {
  688.     if (theMenuList != nil) {
  689.         short ctMenus = (GetHandleSize(theMenuList) - 6) / sizeof(PerMenu);
  690.         short i;
  691.         PerMenu *p = (**theMenuList).permenu;
  692.         for (i = 0;  i < ctMenus;  i++, ++p) {
  693.             if (p->itsHandle != nil)
  694.                 if ((**p->itsHandle).menuID == menuID) {
  695.                     *leftEdge = p->itsLeftEdge;
  696.                     return p->itsHandle;
  697.                 }
  698.         }
  699.     }
  700.     return nil;
  701. }
  702.  
  703. Boolean IsItemEnabled(unsigned long theItem)
  704. {
  705.     reg short menuID = theItem >> 16;
  706.     reg short item = theItem & 0xffff;
  707.     short leftEdge;
  708.     reg MenuHandle foundMenu = FindInstalledMenu(menuID, &leftEdge);
  709.     
  710.     if (foundMenu == nil)
  711.         return false;
  712.  
  713.     return ((**foundMenu).enableFlags & (1 << item)) != 0;
  714. }
  715.  
  716. void SetMouse(Point newLoc)
  717. {
  718.     CrsrCouple = false;
  719.     CrsrNew = true;
  720.     MTemp = RawMouse = Mouse = newLoc;
  721.     CrsrCouple = true;
  722. }
  723.  
  724. void MemZero(void *pp, short l)
  725. {
  726.     asm {
  727.         move.l    pp,a0
  728.         move.w    l,d0
  729.         sub.w    #1,d0
  730.         beq.s   @1
  731.     @0
  732.         clr.b    (a0)+
  733.         dbne.w    d0,@0
  734.     @1
  735.     }
  736. }